﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using System.Reflection;
using System.Xml.Linq;

namespace FileDB
{
    public partial class Reminder : IFileDB
    {
        private string _fileName;

        public string FileName
        {
            get { return _fileName; }
            set { _fileName = value; }
        }


        private int _squ;

        public int SquNum
        {
            get { return _squ; }
            set { _squ = value; }
        }



        public static List<Reminder> GetAllReminder()
        {
            throw new NotImplementedException();
        }

        public Reminder Clone()
        {
            return new Reminder()
            {
                Category = this.Category,
                DueTime = this.DueTime,
                StartTime = this.StartTime,
                Status = ReminderState.Actived,
                Message = this.Message,
                ContractId = this.ContractId
            };
        }
    }

    public partial class Reminder
    {
        public static string RootDir = "Reminders";
        public static string FullRootDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), DataManager.DataDir, RootDir);
        // status-category-contractid-seq
        private static string MetaDataFileName = "0-0-00000000-00000000.xml";

        private static string MetaDataFullFileName = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), DataManager.DataDir, RootDir, MetaDataFileName);

        public static int NextID()
        {
            XDocument xml = XDocument.Load(MetaDataFullFileName);
            return Int32.Parse(xml.Root.Attribute("MaxId").Value) + 1;
        }

        public static int NextSeqID(int contractId)
        {
            if (contractId < 0)
                return 1;
            int result = -1;
            string contract = contractId.ToString("d8");
            XDocument xml = XDocument.Load(MetaDataFullFileName);
            var n = (from x in xml.Descendants("contract")
                     where x.Attribute("id").Value == contract
                     select x);
            if (n.Count() == 1)
            {
                result = Int32.Parse(n.Single().Attribute("maxid").Value) + 1;
            }
            else if (n.Count() == 0)
            {
                result = 1;
            }
            return result;
        }

        public static int Insert(Reminder reminder)
        {
            int reminderId = reminder.Id;
            if (reminderId > 0)
                throw new ArgumentException();
            reminderId = NextID();
            int nextSqeNum = NextSeqID(reminder.ContractId);
            reminder.SquNum = nextSqeNum;
            reminder.Id = reminderId;

            //if (reminder.StartTime.Date <= DateTime.Now.Date)
            //{
            //    reminder.Status = ReminderState.Actived; 
            //}

            string fileName = GetReminderFileName(reminder);
            Save(reminder, fileName);

            UpdateMaxSqeId(reminder.ContractId, nextSqeNum);
            UpdateMaxId(reminderId);

            return reminder.Id;
        }

        private static void Save(Reminder reminder)
        {
            Save(reminder, reminder.FileName);
        }
        private static void Save(Reminder reminder, string fileName)
        {

            XElement r =
                new XElement("Reminder", new XAttribute("Id", reminder.Id), new XAttribute("Sqe", reminder.SquNum),

                    new XElement("BatchId", reminder.BatchId),
                    new XElement("ContractId", reminder.ContractId),
                    new XElement("CreatedTime", reminder.CreatedTime.Date),
                    new XElement("DueTime", reminder.DueTime.Date),
                    new XElement("Message", reminder.Message),
                    new XElement("Category", reminder.Category),
                    new XElement("ReminderTime", reminder.ReminderTime.Date),
                    new XElement("StartTime", reminder.StartTime.Date),
                    new XElement("Status", reminder.Status));
            reminder.FileName = fileName;
            r.Save(fileName);

        }

        private static void UpdateMaxId(int reminderId)
        {
            XDocument xml = XDocument.Load(MetaDataFullFileName);
            xml.Root.Attribute("MaxId").SetValue(reminderId.ToString("d8"));
            xml.Save(MetaDataFullFileName);
        }


        public static string GetReminderFileName(Reminder reminder)
        {
            return Path.Combine(FullRootDir,
                string.Format("{0}-{1}-{2}-{3}.xml",
                (int)ReminderState.Map[reminder.Status],
                (int)ReminderCategory.Map[reminder.Category],
                reminder.ContractId.ToString("d8"),
                reminder.SquNum.ToString("d8")));
        }
        //public static string GetReminderFileName(string category, string state, int contractid, int seq)
        //{
        //    return Path.Combine(FullRootDir,
        //        string.Format("{0}-{1}-{2}-{3}.xml",
        //        (int)RState.Actived,
        //        (int)ReminderCategory.Map[category],
        //        contractid.ToString("d8"),
        //        seq.ToString("d8")));
        //}

        public static List<Reminder> GetReminder(int contractid)
        {
            List<Reminder> reminders = new List<Reminder>();
            var files = Directory.GetFiles(FullRootDir, string.Format("?-?-{0}-*", contractid.ToString("d8")));
            foreach (var file in files)
            {
                reminders.Add(GetReminder(file));
            }
            return ( from r in reminders orderby r.ReminderTime select r ).ToList();
        }

        public static Reminder GetReminder(string fileName)
        {
            XDocument xml = XDocument.Load(fileName);
            var reminder = xml.Root;
            return new Reminder()
            {
                Id = Int32.Parse(reminder.Attribute("Id").Value),
                BatchId = reminder.Element("BatchId").Value,
                ContractId = Int32.Parse(reminder.Element("ContractId").Value),
                CreatedTime = DateTime.Parse(reminder.Element("CreatedTime").Value),
                DueTime = DateTime.Parse(reminder.Element("DueTime").Value),
                Message = reminder.Element("Message").Value,
                Category = reminder.Element("Category").Value,
                ReminderTime = DateTime.Parse(reminder.Element("ReminderTime").Value),
                StartTime = DateTime.Parse(reminder.Element("StartTime").Value),
                Status = reminder.Element("Status").Value,
                FileName = fileName,
                SquNum = Int32.Parse(reminder.Attribute("Sqe").Value),

            };
        }
        private static void UpdateMaxSqeId(int contractId, int nextSqeNum)
        {
            if (contractId < 0)
                throw new ArgumentException();
            string contract = contractId.ToString("d8");
            XDocument xml = XDocument.Load(MetaDataFullFileName);
            var n = (from x in xml.Descendants("contract")
                     where x.Attribute("id").Value == contract
                     select x);
            if (n.Count() == 1)
            {
                n.Single().Attribute("maxid").SetValue(nextSqeNum.ToString("d8"));
            }
            else if (n.Count() == 0)
            {
                xml.Root.Add(new XElement("contract", new XAttribute("id", contract),
                new XAttribute("maxid", nextSqeNum.ToString("d8"))));
            }
            xml.Save(MetaDataFullFileName);
        }

        public static void Update(Reminder reminder)
        {
            string originalFileName = reminder.FileName;
            string newFileName = GetReminderFileName(reminder);
            if (newFileName != originalFileName)
            {
                Reminder.Save(reminder, newFileName);
                File.Delete(originalFileName);
                reminder.FileName = newFileName;
            }
            else
            {
                Reminder.Save(reminder);
            }

        }

        internal static void CreateDefaultTemplate()
        {
            if (File.Exists(MetaDataFullFileName))
                throw new Exception(string.Format("MetaData file already exists", MetaDataFullFileName));

            XElement metadata =
                new XElement("MetaData", new XAttribute("MaxId", 0.ToString("d8")),
                    new XElement("contract",
                        new XAttribute("id", 0.ToString("d8")),
                        new XAttribute("maxid", 0.ToString("d8"))));
            metadata.Save(MetaDataFullFileName);
        }

        public static void Delete(Reminder r)
        {
            if (File.Exists(r.FileName))
            {
                File.Delete(r.FileName);
            }
        }

        public static List<Reminder>
            GeneratePeriodReminder(Reminder remider, Contract contract, int advancedDays, int interval)
        {
            List<Reminder> reminders = new List<Reminder>();
            reminders = new List<Reminder>();
            Guid batch = Guid.NewGuid();

            DateTime start = remider.StartTime;
            DateTime end = remider.DueTime;
            int delta = (remider.ReminderTime - start).Days - advancedDays;

            while (start <= end)
            {
                Reminder r = new Reminder();
                r.Category = remider.Category;
                r.Status = remider.Status;
                r.BatchId = batch.ToString();
                r.CreatedTime = remider.CreatedTime;
                r.Message = remider.Message;
                r.ContractId = remider.ContractId;
                if (start.AddMonths(interval).AddDays(-1).Date <= end.Date)
                {

                    r.StartTime = start;
                    r.ReminderTime = start.AddDays(delta);
                    r.DueTime = start.AddMonths(interval).AddDays(-1);
                    start = start.AddMonths(interval);
                    if (string.IsNullOrEmpty(remider.Message) && remider.ContractId > 0)
                    {
                        double rent = 0.0;
                        if (contract.RentUnit == Contract.RentUnit_Month)
                        {
                            rent = (contract.RentPerInterval * interval);
                        }
                        else if (contract.RentUnit == Contract.RentUnit_Year)
                        {
                            rent = contract.RentPerInterval * interval / 12.0;
                        }
                        r.RelatedRent = rent;
                        r.Message = string.Format("门面地址:{0} 收租方:{1} 缴租方:{2} 金额:{3} 起止日期:{4}到{5} 开票:{6}",
                            contract.Address,
                            Customer.GetCustomer(contract.PartAId).Name,
                            Customer.GetCustomer(contract.PartBId).Name,
                            rent.ToString("###,###,##0"),
                            r.StartTime.Date.ToString("yyyy-MM-dd"),
                            r.DueTime.Date.ToString("yyyy-MM-dd"),
                            contract.CanTicket ? "是" : "否"
                            );
                    }
                }
                else
                {
                    r.StartTime = start;
                    r.ReminderTime = start.AddDays(delta);
                    r.DueTime = end;

                    if (string.IsNullOrEmpty(remider.Message) && remider.ContractId > 0)
                    {
                        int months = 0;
                        int days = 0;
                        while (months < interval)
                        {
                            if (start.AddMonths(months + 1).AddDays(-1).Date < end.Date)
                            {
                                months++;
                            }
                            else
                            {
                                break;
                            }
                        }
                        //todo check
                        days = (end - start.AddMonths(months)).Days + 1;
                        double rent = 0.0;
                        if (contract.RentUnit == Contract.RentUnit_Month)
                        {
                            rent = (contract.RentPerInterval * months + contract.RentPerInterval * days / 30);
                        }
                        else if (contract.RentUnit == Contract.RentUnit_Year)
                        {
                            rent = rent = contract.RentPerInterval * months / 12.0 +
                                contract.RentPerInterval * days / 365;
                        }
                        r.RelatedRent = rent;
                        r.Message = string.Format("门面地址:{0} 收租方:{1} 缴租方: {2} 金额:{3} 起止日期: {4}到{5} 开票:{6}",
                            contract.Address,
                            Customer.GetCustomer(contract.PartAId).Name,
                            Customer.GetCustomer(contract.PartBId).Name,
                            rent.ToString("###,###,##0"),
                            r.StartTime.Date.ToString("yyyy-MM-dd"),
                            r.DueTime.Date.ToString("yyyy-MM-dd"),
                            contract.CanTicket ? "是" : "否"
                            );

                    }
                    start = end.AddDays(1);
                }
                reminders.Add(r);
            }
            return reminders;
        }

        
    }
}


